package ma.controller.panels;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import ma.controller.gui.Controllable;
import ma.controller.panels.auxillary.CalculateButtonListener;
import ma.controller.panels.auxillary.CtrInformationPanel;
import ma.controller.panels.parameterpanels.CtrResultsPanel;
import ma.controller.panels.CtrInOut;
import ma.model.EBenchmarkInterface;
import ma.model.ManufacturingMethodInterface;
import ma.view.gui.EBenchmarkPanel;
import ma.view.gui.ObserverInterface;
import ma.view.gui.SetupMethods;
import ma.view.gui.CenterTabbedPane.EBenchmarkTab;
/**
 * The {@code CtrSetupMethods} controls the behavior of the panel where the
 * user can setup the selected manufacturing methods. The panel can be seen
 * as the main panel as the user always sees it before or after setting up
 * a manufacturing method.
 * @author Oliver Eckstein
 *
 */
public class CtrSetupMethods implements Controllable {
    // The panel's view.
    private SetupMethods methodsSetupPanel;
    
    private EBenchmarkInterface eBenchmark;
    private CtrInformationPanel infoPanelController;
    private CtrCenterTabbedPane tabbedPaneController;        
    private CtrInOut inputOutputController;
    private CtrResultsPanel resultPanelController;
    
    private ManufacturingMethodInterface activeManuMethod;
    
    // Listener for the button which starts the calculation for the active
    // manufacturing method.
    private ActionListener calculateListener;
    
    /**
     * To create a new instance of a {@code CtrSetupMethods} and connect it
     * to the model, the controller of the information panel and the controller
     * of the main {@code JTabbedPane}.
     * @param eBenchmark the application's model.
     * @param infoPanelController the controller of the information panel.
     * @param tabbedPaneController the controller of the tabbed pane.
     */
    public CtrSetupMethods(
            EBenchmarkInterface eBenchmark,
            CtrInformationPanel infoPanelController,
            CtrCenterTabbedPane tabbedPaneController) {
        this.eBenchmark = eBenchmark;
        this.infoPanelController = infoPanelController;
        this.tabbedPaneController = tabbedPaneController;
        
        this.infoPanelController
            .registerSetupConfirmListener(createSetupConfirmListener());
                
        this.infoPanelController
            .registerStoreDataListener(createStoreDataActionListener());
        
        this.infoPanelController
            .registerCalculateAllListener(createCalculateAllListener());
        
        this.infoPanelController
            .registerCloseResultsListener(createCloseResultsListener());
        
        methodsSetupPanel = new SetupMethods(this.eBenchmark,
                infoPanelController.getView());        
    }   
    
    /**
     * Once the user chooses to enter parameters for a manufacturing method
     * new tabs get added to the main tabbed pane. Both for data/parameter
     * input and output/results for the specified manufacturing method.
     */
    private void addManufacturingTabs() {
        // Add new view components and connect them to the choosen
        // manufacturing method.
        String selectedManuMethod = methodsSetupPanel.getSelectedButtonText();
        
        if (selectedManuMethod == null) {
            return;
        }
        
        activeManuMethod =
                eBenchmark.getManufacturingMethod(selectedManuMethod);
        activeManuMethod.registerObserver(tabbedPaneController.getView());        
        inputOutputController =
                new CtrInOut(activeManuMethod, infoPanelController);
        
        calculateListener =
                new CalculateButtonListener(
                        activeManuMethod,
                        inputOutputController
                            .getResultParameterPanelController(),
                        tabbedPaneController);
        infoPanelController.registerCalculateListener(calculateListener);
        
        // Register the methods setup panel to the manufacturing method to
        // make sure that the status of the methods setup panel gets updated.
        activeManuMethod.registerObserver(
                methodsSetupPanel.getMethodsSetupPanel(selectedManuMethod));
        
        // Register every new tab to the manufacturing method.
        for (ObserverInterface observer : inputOutputController.getViews()) {
            activeManuMethod.registerObserver(observer);
        }
        
        // Add the new tabs behind the setup methods tab.
        tabbedPaneController.getView()
            .addPanels(inputOutputController.getViews(),
                    EBenchmarkTab.SETUP_METHODS.ordinal() + 1);
        
        tabbedPaneController.getView().update();        
        tabbedPaneController
            .getView().showTab(EBenchmarkTab.PROCESS_PARAMETERS);
    }
    
    /**
     * Once the user clicked the button to store the data all previously added
     * tabs in must be deleted again.
     */
    private void removeManufacturingTabs() {
        // Remove the panels and unregister the observers.
        tabbedPaneController.getView()
            .remove(inputOutputController.getViews());        
        for (ObserverInterface observer : inputOutputController.getViews()) {
            activeManuMethod.removeObserver(observer);
        }
        infoPanelController.removeCalculateListener(calculateListener);
        activeManuMethod.removeObserver(
                methodsSetupPanel.getMethodsSetupPanel(
                        methodsSetupPanel.getSelectedButtonText()));
        inputOutputController = null;
        activeManuMethod = null;
    }
    
    /**
     * Adds the main results tab.
     */
    private void addResultTab() {
        resultPanelController = new CtrResultsPanel(eBenchmark);
        tabbedPaneController.getView().addPanel(resultPanelController.getView(),
                tabbedPaneController.getView().getTabCount());
        tabbedPaneController.getView().showTab(EBenchmarkTab.SHOW_END_RESULTS);
        infoPanelController.disableCalculateAll();
    }
    
    /**
     * Removes the main results tab.
     */
    private void removeResultTab() {
        tabbedPaneController.getView().remove(EBenchmarkTab.SHOW_END_RESULTS);
        tabbedPaneController.getView().showTab(EBenchmarkTab.SETUP_METHODS);
        resultPanelController = null;
        infoPanelController.enableCalculateAll();
    }

    private ActionListener createStoreDataActionListener() {
        return new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                tabbedPaneController
                    .getView().showTab(EBenchmarkTab.SETUP_METHODS);
                if(eBenchmark.allSet()) {
                    infoPanelController.enableCalculateAll();
                } else {
                    infoPanelController.disableCalculateAll();
                }
                removeManufacturingTabs();
            }            
        };
    }
    
    private ActionListener createSetupConfirmListener() {
        return new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if (activeManuMethod == null) {
                    if (inputOutputController != null) {
                        removeManufacturingTabs();    
                    }        
                    addManufacturingTabs();
                    infoPanelController.disableCalculateAll();
                }
            }
        };
    }
    
    private ActionListener createCalculateAllListener() {
        return new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if(eBenchmark.calculateAll()) {
                    eBenchmark.calculate();
                    addResultTab();
                    tabbedPaneController
                        .getView().showTab(EBenchmarkTab.SHOW_END_RESULTS);    
                }                
            }            
        };
    }
    
    private ActionListener createCloseResultsListener() {
        return new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                removeResultTab();                
            }
            
        };
    }
    
    @Override
    /*
     * (non-Javadoc)
     * @see ma.controller.gui.Controllable2#getView()
     */    
    public EBenchmarkPanel getView() {
        return methodsSetupPanel;
    }
}
